package cn.liziguo.tank.util;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Liziguo
 * @date 2022-05-21 16:46:51
 */
public class JsonUtil {

    private static final ObjectMapper objectMapper;

    private static final TypeFactory typeFactory;

    static {
        objectMapper = new ObjectMapper();

        typeFactory = TypeFactory.defaultInstance();

        // 序列化java.time.LocalDateTime用的
        /* 需要引入
            <dependency>
                <groupId>com.fasterxml.jackson.datatype</groupId>
                <artifactId>jackson-datatype-jsr310</artifactId>
            </dependency>
         */
//        objectMapper.registerModule(new JavaTimeModule());
        // 日期序列化
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        // 字符串上有的字段 但java实体类上没有时不报错
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 不允许基本类型为null 如果为null会报错 字符串没有该字段的话不会报错 会给java对象的该字段赋默认值(只有字符串中有该字段 且值为null是会报错)
        objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true);
        // 忽略null 空数组不会忽略 空串空数组会被打印
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 忽略空的 空串 空数组
//        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
        // 忽略默认属性 空串 整数0 空数组 false都会被忽略
//        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
    }

    /**
     * 解析json字节数组
     *
     * @param json  json字符串
     * @param clazz T.class 或 T[].class
     * @return T
     */
    public static <T> T parse(byte[] json, Class<T> clazz) {
        try {
            return objectMapper.readValue(json, clazz);
        } catch (IOException e) {
            throw new JsonProcessingRuntimeException(e);
        }
    }

    /**
     * 解析json字符串
     *
     * @param json  json字符串
     * @param clazz T.class 或 T[].class
     * @return T
     */
    public static <T> T parse(String json, Class<T> clazz) {
        try {
            return objectMapper.readValue(json, clazz);
        } catch (JsonProcessingException e) {
            throw new JsonProcessingRuntimeException(e);
        }
    }

    public static <T> List<T> parseArray(byte[] json, Class<T> clazz) {
        try {
            return objectMapper.readValue(json, typeFactory.constructCollectionType(ArrayList.class, clazz));
        } catch (IOException e) {
            throw new JsonProcessingRuntimeException(e);
        }
    }

    public static <T> List<T> parseArray(String json, Class<T> clazz) {
        try {
            return objectMapper.readValue(json, typeFactory.constructCollectionType(ArrayList.class, clazz));
        } catch (JsonProcessingException e) {
            throw new JsonProcessingRuntimeException(e);
        }
    }

    public static Map<String, Object> parseMap(byte[] json) {
        try {
            return objectMapper.readValue(json, typeFactory.constructMapType(LinkedHashMap.class, String.class, Object.class));
        } catch (IOException e) {
            throw new JsonProcessingRuntimeException(e);
        }
    }

    public static Map<String, Object> parseMap(String json) {
        try {
            return objectMapper.readValue(json, typeFactory.constructMapType(LinkedHashMap.class, String.class, Object.class));
        } catch (JsonProcessingException e) {
            throw new JsonProcessingRuntimeException(e);
        }
    }

    public static <T> T convertValue(Object fromValue, Class<T> toValueType) {
        return objectMapper.convertValue(fromValue, toValueType);
    }

    public static <T> T convertValue(Object fromValue, TypeReference<T> toValueTypeRef) {
        return objectMapper.convertValue(fromValue, toValueTypeRef);
    }

    public static <T> T convertValue(Object fromValue, JavaType toValueType) {
        return objectMapper.convertValue(fromValue, toValueType);
    }

    public static byte[] toBytes(Object o) {
        try {
            return objectMapper.writeValueAsBytes(o);
        } catch (JsonProcessingException e) {
            throw new JsonProcessingRuntimeException(e);
        }
    }

    public static String toString(Object o) {
        try {
            return objectMapper.writeValueAsString(o);
        } catch (JsonProcessingException e) {
            throw new JsonProcessingRuntimeException(e);
        }
    }

    public static class JsonProcessingRuntimeException extends RuntimeException {

        public JsonProcessingRuntimeException() {
            super();
        }

        public JsonProcessingRuntimeException(String message) {
            super(message);
        }

        public JsonProcessingRuntimeException(String message, Throwable cause) {
            super(message, cause);
        }

        public JsonProcessingRuntimeException(Throwable cause) {
            super(cause);
        }

        protected JsonProcessingRuntimeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
            super(message, cause, enableSuppression, writableStackTrace);
        }

    }
}
